/*****************************************************************
 * Filename   | Example_Programs.cpp
 * Author     | Scott J. Schneider 
 *
 * Assignment | Programming Exercise for ECT362
 * Due date   | 01/01/07
 *****************************************************************/

/*****************************************************************
 * Problem Statement | 
 *
 * Inputs            | 
 * Outputs           | 
 * Processes         | 
 * 
 * Pseudocode Design | 1.
 *                   | 2. 
 *                   | 3. 
 *                   | 4. 
 ******************************************************************/

/* Preprocessor Directives */
#include <windows.h>  // Win32 API
#include <process.h>  // process & thread
#include "Resource.h"  // resources for your application
#include <string.h>
#include <stdio.h>
#include <fstream>


#define ID_ADDBUTTON    1001 //IDs for components 
#define ID_DELETEBUTTON 1002
#define ID_LIST                 1010
#define ID_FNAME                1020
#define ID_LNAME                1021
#define ID_PHN                  1022
#define ID_EMAIL                1023
#define COLS 100

 struct ContactInfo { // struct for contacts
        char fnames[100];
        char lnames[100];
        char emails[100];
        char phnums[100];
}contacts[100];

int in_cnt = 0, out_cnt = 0, file_limit; // global variables used for tracking contacts
int row = 0;
int row_cnt = 0;
int len;
char name[100];
char newline[100] = "    ";
char line[COLS];
char temp[100];


/* Function Prototypes */
LRESULT CALLBACK WndProc( HWND, UINT, WPARAM, LPARAM );  //the window procedure
/* A callback function is passed (by reference) to another function */
DWORD WINAPI addthread( LPVOID ); // creates function for adding to the listbox
DWORD WINAPI deletethread( LPVOID ); // creates function for delete
DWORD WINAPI refreshthread( LPVOID ); // creates function for refresh

/* Global variables */

/* Functions */
/*****************************************************************
 * Function    | WinMain()
 * Description | Entry point for our application, we create and 
 *             |  register a window class and then call CreateWindow
 * Inputs      | None
 * Output      | Integer value 0
 *****************************************************************/ 
int WINAPI WinMain( HINSTANCE hInstance, 
                                    HINSTANCE hPrevInstance,
                    LPSTR szCmdLine, 
                                        int iCmdShow ) 
{
    static char szAppName[] = "My Contacts";
        
        HWND        hwnd;
    WNDCLASSEX  wndclass;  // This is our new windows class
        MSG msg;

        /*  Fill in WNDCLASSEX struct members  */
    wndclass.cbSize         = sizeof(wndclass);
    wndclass.style          = CS_HREDRAW | CS_VREDRAW;
    wndclass.lpfnWndProc    = WndProc;
    wndclass.cbClsExtra     = 0;
    wndclass.cbWndExtra     = 0;
    wndclass.hInstance      = hInstance;
    wndclass.hIcon          = LoadIcon(GetModuleHandle(NULL), MAKEINTRESOURCE(IDI_MyIcon));
    wndclass.hIconSm        = (HICON)LoadImage(GetModuleHandle(NULL), MAKEINTRESOURCE(IDI_MyIcon), IMAGE_ICON, 16, 16, 0);
    wndclass.hCursor        = LoadCursor(NULL, IDC_ARROW);
    wndclass.hbrBackground  = (HBRUSH) GetStockObject(WHITE_BRUSH);
    wndclass.lpszClassName  = szAppName;
    wndclass.lpszMenuName   = NULL;

    /*  Register a new window class with Windows  */
    RegisterClassEx(&wndclass);

    /*  Create a window based on our new class  */
    hwnd = CreateWindow(szAppName,  // class name the window is to be based on 
                                                "My Contacts",  // the title of the window that will 
                                                                  //  appear in the bar at the top
                                                WS_OVERLAPPEDWINDOW,  // window style (a window that 
                                                                      //  has a caption, a system menu, 
                                                                                          //  a thick frame and a minimise 
                                                                                          //  and maximise box)
                                                /* Use default starting location for window */
                                                CW_USEDEFAULT, // initial x position (top left corner)
                                                CW_USEDEFAULT, // initial y position (top left corner)
                                                830, // initial width
                                                500, // initial height
                                                NULL, // window parent (NULL for not a child window)
                                                NULL, // menu (NULL to use class menu)
                                                hInstance, // the program instance passed to us
                                                NULL);  // pointer to any parameters wished to be 
                                    //  passed to the window producer when the window
                                    //  is created
 
        if(hwnd == NULL)  // check to see if an error occurred in creating the window
    {
        MessageBox(NULL, "Window Creation Failed!", "Error!",
            MB_ICONEXCLAMATION | MB_OK);
        return 0;
    }

    /* Show and update our window  */
    ShowWindow(hwnd, iCmdShow);
    UpdateWindow(hwnd);

 
        /*  Retrieve and process any queued messages until we get WM_QUIT  */
        /* Recall that Windows uses a messaging system to notify window of */
        /*  user actions                                                                                                   */
    while ( GetMessage(&msg, NULL, 0, 0) ) 
        {
                TranslateMessage(&msg);  // for certain keyboard messages 
                DispatchMessage(&msg);  // send message to WndProc
    } 

    /*  Exit with status specified in WM_QUIT message  */
    return msg.wParam;
} // end WinMain()


/*****************************************************************
 * Function    | WinProc()
 * Description | Whenever anything happens to your window, Windows 
 *             |  will call this function telling you what has happened. 
 *             |  The message parameter contains the message sent
 * Inputs      | None
 * Output      | Integer value 0
 *****************************************************************/ 
LRESULT CALLBACK WndProc( HWND hwnd, 
                                                  UINT iMsg, 
                                                  WPARAM wParam, 
                                                  LPARAM lParam ) 
{
    PAINTSTRUCT ps;
        HDC hdc;
        static HWND  addbutton, listbox, fname, lname, phn, email, deletebutton, thread_hwnds[6]; //threads used for passing data 
                
        HANDLE aThread; // declarte handle for thread associated with ADD button
        HANDLE dThread;
        HANDLE fThread;
        LPSECURITY_ATTRIBUTES lpsa = NULL; //
        DWORD dwStackSize = 0; //
        DWORD dwCreationFlags = 0; //
        DWORD aThreadID; // establishes the three broken out prcesses with IDs
        DWORD dThreadID;
        DWORD rThreadID;
        
        int len;
        int i = 0;
        char name[100];
        char nametest[100] = "Type Contact Info here"; 
        char new_contact;
        char line[COLS];

        /*  Switch according to what type of message we have received  */
    switch ( iMsg ) 
        {
                case WM_PAINT:
                /* We receive WM_PAINT every time window is updated  */
                        //hdc = BeginPaint(hwnd, &ps);
                        //TextOut(hdc, 10, 160, "My First Window", 15);
                        //EndPaint(hwnd, &ps);
                        break;
                case WM_CREATE:
        /* Operations to be performed whenthis window is created */ 
                        /* Create a child window for a pushbutton */
                        addbutton = CreateWindow(  "BUTTON",  // predefined class 
                                                                "Add Contact",  // button text 
                                                                WS_VISIBLE | WS_CHILD | BS_PUSHBUTTON, 
                                                                // Size and position values are given 
                                                                //  explicitly, because the CW_USEDEFAULT 
                                                                //  constant gives zero values for buttons. 
                                                                690,  // starting x position 
                                                                420,  // starting y position 
                                                                100, // button width 
                                                                30,  // button height 
                                                                hwnd, // parent window 
                                                                (HMENU)ID_ADDBUTTON, // no menu 
                                                                (HINSTANCE) 0,  // ignored for Windows XP
                                                                NULL );  // pointer not needed 
                        deletebutton = CreateWindow(  "BUTTON",  // predefined class 
                                                                "Delete Contact",  // button text 
                                                                WS_VISIBLE | WS_CHILD | BS_PUSHBUTTON, 
                                                                // Size and position values are given 
                                                                //  explicitly, because the CW_USEDEFAULT 
                                                                //  constant gives zero values for buttons. 
                                                                690,  // starting x position 
                                                                10,  // starting y position 
                                                                110, // button width 
                                                                30,  // button height 
                                                                hwnd, // parent window 
                                                                (HMENU)ID_DELETEBUTTON, // no menu 
                                                                (HINSTANCE) 0,  // ignored for Windows XP
                                                                NULL );  // pointer not needed 
                        
                        /* Create a list box to display values within the window */
                        listbox = CreateWindow( "LISTBOX",  // predefined class
                                                                    "",  // initial lst box text (empty)
                                                                        // automatically sort items in list box 
                                                                        //  and include a vertical scroll bar 
                                                                        //  with a border
                                                                    WS_CHILD | WS_VISIBLE | LBS_NOTIFY | 
                                                                        WS_VSCROLL | WS_BORDER,  
                                                                        10,  // starting x position
                                                                        10,  // starting y position
                                                                        550,  // list box width
                                                                        300,  // list box height
                                                                        hwnd,  // parent window
                                                                        (HMENU)ID_LIST,  // no menu
                                                                        (HINSTANCE) 0,  // ignored for Windows XP
                                                                        NULL ); // pointer not needed
                                                FILE *file_ptr;
        
                                /* Read command line information */
        

                                file_ptr = fopen("contacts.txt", "r");  // open the contacts.txt file for 
                                                                                                           //  reading only
                                if( file_ptr == NULL ) // failed to open file
                                {
                                        MessageBox(NULL, "ERROR OPENING FILE","Error Opening Contact File", MB_ICONINFORMATION | MB_OK); 
                                        exit( 0 );  // exit program
                                }

                                /* Read file line-by-line, storing each line into a seperate row in */
                                /*  the names[][] string array                                                                      */
                                while( fgets( line, COLS, file_ptr) != NULL )
                                {
                                        sscanf(line, "%s\t%s\t%s\t%s", contacts[in_cnt].fnames, contacts[in_cnt].lnames, contacts[in_cnt].emails, contacts[in_cnt].phnums);
                                        char temp[100]; // adds contacts to array before going into the listbox
                                                        strcpy(temp, contacts[in_cnt].fnames);
                                                        strcat(temp, " " );
                                                        strcat(temp, contacts[in_cnt].lnames);
                                                        strcat(temp, " " );
                                                        strcat(temp, contacts[in_cnt].phnums);
                                                        strcat(temp, " " );
                                                        strcat(temp, contacts[in_cnt].emails);
                                                        puts(temp);
                                        if(temp != newline)
                                        {
                                                SendDlgItemMessage( hwnd, ID_LIST, LB_ADDSTRING, 0, LPARAM(temp)); // adds line to listbox
                                                in_cnt++;  // increment to next row in first and last name arrays 
                                        }

                                }
                                file_limit = in_cnt;  // store location of any new data entered from user
                                fclose(file_ptr);  //close file since all data has been extracted


                        /* Create edit box for adding and deleting items from list */
                        fname = CreateWindow( "EDIT",  // predefined class
                                                    "First Name",  // initial lst box text (empty)
                                                                        // create an edit box with a border
                                                                        WS_CHILD | WS_VISIBLE | WS_BORDER, 
                                                                        10,  // starting x position
                                                                        425,  // starting y position
                                                                        160,  // list box width
                                                                        20,  // list box height
                                                                        hwnd,  // parent window
                                                                        (HMENU)ID_FNAME,  // no menu
                                                                        (HINSTANCE) 0,  // ignored for Windows XP
                                                                        NULL); // pointer not needed
                        lname = CreateWindow( "EDIT",  // predefined class
                                                    "Last Name",  // initial lst box text (empty)
                                                                        // create an edit box with a border
                                                                        WS_CHILD | WS_VISIBLE | WS_BORDER, 
                                                                        180,  // starting x position
                                                                        425,  // starting y position
                                                                        160,  // list box width
                                                                        20,  // list box height
                                                                        hwnd,  // parent window
                                                                        (HMENU)ID_LNAME,  // no menu
                                                                        (HINSTANCE) 0,  // ignored for Windows XP
                                                                        NULL); // pointer not needed
                        phn = CreateWindow( "EDIT",  // predefined class
                                                    "Phone Number",  // initial lst box text (empty)
                                                                        // create an edit box with a border
                                                                        WS_CHILD | WS_VISIBLE | WS_BORDER, 
                                                                        350,  // starting x position
                                                                        425,  // starting y position
                                                                        160,  // list box width
                                                                        20,  // list box height
                                                                        hwnd,  // parent window
                                                                        (HMENU)ID_PHN,  // no menu
                                                                        (HINSTANCE) 0,  // ignored for Windows XP
                                                                        NULL); // pointer not needed
                        email = CreateWindow( "EDIT",  // predefined class
                                                    "Email",  // initial lst box text (empty)
                                                                        // create an edit box with a border
                                                                        WS_CHILD | WS_VISIBLE | WS_BORDER, 
                                                                        520,  // starting x position
                                                                        425,  // starting y position
                                                                        160,  // list box width
                                                                        20,  // list box height
                                                                        hwnd,  // parent window
                                                                        (HMENU)ID_EMAIL,  // no menu
                                                                        (HINSTANCE) 0,  // ignored for Windows XP
                                                                        NULL); // pointer not needed
                        break;
                case WM_DESTROY:
                /* Window has been destroyed, so exit cleanly  */
                        PostQuitMessage(0);
                        break;
                case WM_COMMAND:
            /* User selected a command from a menu or a control sent a message */
                        if (HIWORD(wParam) == BN_CLICKED) 
            { 
                switch (LOWORD(wParam)) 
                { 
                                        case ID_ADDBUTTON:
                                                {
                                                /* set the HWND array for passing to thread */
                                                thread_hwnds[0] = hwnd;  // pass handle of parent 
                                                                                                 //  window
                                                thread_hwnds[1] = fname; // pass handle to textbox
                                                thread_hwnds[2] = lname;
                                                thread_hwnds[3] = phn;
                                                thread_hwnds[4] = email;
                                                thread_hwnds[5] = listbox;
                                                //needs to be moded to allow for additional access to the different editboxes 
                                                /* Create thread for performing actions associated */
                                                /*  with ADD button                                */
                                                aThread = (HANDLE) CreateThread(
                                                                   lpsa,
                                                               dwStackSize,
                                                               (LPTHREAD_START_ROUTINE)addthread, //tells it where it's headed 
																(LPVOID) &thread_hwnds,
                                                                   dwCreationFlags,
                                                                   (LPDWORD) &aThreadID );
                                                break; 
                                                }
                                        case ID_DELETEBUTTON:
                                        {
                                                /* set the HWND array for passing to thread */
                                                thread_hwnds[0] = hwnd;  // pass handle of parent 
                                                                                                 //  window
                                                thread_hwnds[1] = fname; // pass handle to textbox
                                                thread_hwnds[2] = lname;
                                                thread_hwnds[3] = phn;
                                                thread_hwnds[4] = email;
												thread_hwnds[5] = listbox;
                                                dThread = (HANDLE) CreateThread(
                                                                   lpsa,
                                                               dwStackSize,
                                                               (LPTHREAD_START_ROUTINE)deletethread, //tells it where it's headed 
																(LPVOID) &thread_hwnds,
                                                                   dwCreationFlags,
                                                                   (LPDWORD) &aThreadID );

                                                break;
                                        }
                                }
                        }
                        break;
                default:
        /* We do not want to handle this message so pass back to Windows */
        /*  to handle it in a default way                                */
                        return DefWindowProc(hwnd, iMsg, wParam, lParam);
        }
        return 0;

} // end WndProc

DWORD WINAPI addthread(LPVOID hwnd_addr)
{
        HWND *thread_hwnds, hwnd, Afname, Alname, Aphn, Aemail;
        DWORD result = 0;

        thread_hwnds = (HWND *)hwnd_addr;
        hwnd = thread_hwnds[0]; // extract parent window handle
        Afname = thread_hwnds[1];  // extract textbox handle
        Alname = thread_hwnds[2];
        Aphn = thread_hwnds[3];
        Aemail = thread_hwnds[4];
        MessageBox(NULL, "Add Button Pressed", "ADD", MB_ICONINFORMATION | MB_OK);

       /* Read length of string entered into the text box */
        len = GetWindowTextLength(Afname);  
        /* Read string from edit box and store to name[] */
        GetWindowText(Afname, name, len + 1); 
        if(len == 0)
        {
			MessageBox(NULL, "No Contact Information", "No Contact", MB_ICONINFORMATION | MB_OK); // tests to see if a contact has been added 
        }
        else
        {
        //need to add new line to struct
		GetWindowText(Afname,contacts[in_cnt].fnames, len + 1); // gets length ot contact then adds to struct
        len = GetWindowTextLength(Alname);
        GetWindowText(Alname, contacts[in_cnt].lnames, len + 1);
        len = GetWindowTextLength(Aphn);
        GetWindowText(Aphn, contacts[in_cnt].phnums, len + 1);
        len = GetWindowTextLength(Aemail);
        GetWindowText(Aemail, contacts[in_cnt].emails, len + 1);
                
        char temp[100]; // pulls from struct new contact then formats the info to be added to the list box
        strcpy(temp, contacts[in_cnt].fnames);
        strcat(temp, " " );
        strcat(temp, contacts[in_cnt].lnames);
        strcat(temp, " " );
        strcat(temp, contacts[in_cnt].phnums);
        strcat(temp, " " );
        strcat(temp, contacts[in_cnt].emails);
        puts(temp);
        SendDlgItemMessage( hwnd, ID_LIST, 
                            LB_ADDSTRING, 0, 
                           (LPARAM)temp); // adds to listbox
        SetWindowText(Afname,""); //clears text fields
        SetWindowText(Alname, "");
        SetWindowText(Aphn, "");
        SetWindowText(Aemail, "");
        in_cnt++;
        MessageBox(NULL, "Contact Added", "Contact Added", MB_ICONINFORMATION | MB_OK); // confirms add
        
		/* Simulate file I/O time over the congested network */
        Sleep(1000);

		}
        return result;
                                                
        //NOTES: On refresh may be easier to force the contacts reload rather than checking to see if the vals have changed, just force and update 
        //check ability to run a thread periodically in the thread structure, list all variables as globals for entire program 

}

DWORD WINAPI deletethread(LPVOID hwnd_addr)
{
        HWND *thread_hwnds, hwnd, Dfname, Dlname, Dphn, Demail;
        DWORD result = 0;

        thread_hwnds = (HWND *)hwnd_addr;
        hwnd = thread_hwnds[0]; // extract parent window handle
        Dfname = thread_hwnds[1];  // extract textbox handle
        Dlname = thread_hwnds[2];
        Dphn = thread_hwnds[3];
        Demail = thread_hwnds[4];
        MessageBox(NULL, "Delete Button Pressed", "Delete", MB_ICONINFORMATION | MB_OK);
		
		row = SendDlgItemMessage(hwnd, ID_LIST, LB_GETCURSEL, 0,0); // gets row id
        if(row <= -1) // allows the delete to function to exit if the user does not select a row
        {
			MessageBox(NULL,"To remove a contact, first click to highlight the desired contact. Then click the delte button",  "How To Remove Contacts", MB_ICONINFORMATION | MB_OK); 
            return result;
        }
        SendDlgItemMessage(hwnd, ID_LIST, LB_DELETESTRING, WPARAM(row), 0); //deletes selected row using the row id
        row_cnt = in_cnt;
        for(int i= 0; i < row_cnt; i++) // removes old contact by overwriting it in the struct
        {
			contacts[row] = contacts[row + 1];

        }
        in_cnt--; // decrements count 
        MessageBox(NULL, "Contact Deleted", "Contact Deleted", MB_ICONINFORMATION | MB_OK); // confirms delete
        
        return result;
        //NOTES: On refresh may be easier to force the contacts reload rather than checking to see if the vals have changed, just force and update 
        //check ability to run a thread periodically in the thread structure, list all variables as globals for entire program 

}

DWORD WINAPI refreshthread(LPVOID hwnd_addr)
{
        DWORD result = 0;
        HWND *thread_hwnds, hwnd, listbox;
        thread_hwnds = (HWND *)hwnd_addr;
        hwnd = thread_hwnds[0];
        listbox = thread_hwnds[5];

        FILE *file_ptr;
        SendDlgItemMessage(hwnd, ID_LIST, LB_RESETCONTENT, 0, 0);

        file_ptr = fopen("contacts.txt", "r");  // open the contacts.txt file for 
                                                                                                           //  reading only
                                if( file_ptr == NULL ) // failed to open file
                                {
                                        MessageBox(NULL, "ERROR OPENING FILE","Error Opening Contact File", MB_ICONINFORMATION | MB_OK); 
                                        exit( 0 );  // exit program
                                }

                                /* Read file line-by-line, storing each line into a seperate row in */
                                /*  the names[][] string array                                                                      */
                                while( fgets( line, COLS, file_ptr) != NULL )
                                {
                                        sscanf(line, "%s\t%s\t%s\t%s", contacts[in_cnt].fnames, contacts[in_cnt].lnames, contacts[in_cnt].emails, contacts[in_cnt].phnums);
                                         // adds contacts to array before going into the listbox
                                                        strcpy(temp, contacts[in_cnt].fnames);
                                                        strcat(temp, " " );
                                                        strcat(temp, contacts[in_cnt].lnames);
                                                        strcat(temp, " " );
                                                        strcat(temp, contacts[in_cnt].phnums);
                                                        strcat(temp, " " );
                                                        strcat(temp, contacts[in_cnt].emails);
                                                        puts(temp);
                                        if(temp != newline)
                                        {
                                                SendDlgItemMessage( hwnd, ID_LIST, LB_ADDSTRING, 0, LPARAM(temp)); // adds line to listbox
                                                in_cnt++;  // increment to next row in first and last name arrays 
                                        }

                                }
                                file_limit = in_cnt;  // store location of any new data entered from user
                                fclose(file_ptr);  //close file since all data has been extracted



        return result;
}
